package com.mxy.myapplication.util;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.util.SparseArrayCompat;
import android.support.v7.widget.RecyclerView;

import com.google.gson.reflect.TypeToken;
import com.mxy.myapplication.R;
import com.mxy.myapplication.activity.DownLoadScheduleActivity;
import com.mxy.myapplication.asynctask.AsyncTaskForDownloadFile;
import com.mxy.myapplication.pojo.DownloadMissionPojo;

import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.util.ArrayList;

/**
 * 下载任务管理类
 *
 * @author 马晓勇
 */
public class DownloadMissionManageUtil {

    /**
     * 刷新时间间隔   单位秒
     */
    public static final int MISSION_REFRESH_TIME_INTERVAL = 3;
    public static final String BROADCAST_MISSIONCOMPLETED = "missioncompleted";
    public static final String FILE_ADDRESS_INTENT_KEY = "fileaddress";
    private static final String DOWNLOADMISSIONS_CACHE_KEY = "downloadmissionsjsoncache";
    private static final String NOTIFICATION_CHANNEL_ID = "2";
    private static final String NOTIFICATION_CHANNEL_NAME = "downloadNotificationChannel";

    private static ArrayList<DownloadMissionPojo> missionList = new ArrayList<>(3);
    private static SparseArrayCompat<AsyncTask> taskArray = new SparseArrayCompat<>(3);
    private static NotificationCompat.Builder notificationBuilder;
    private static NotificationManager notificationManager;
    private static WeakReference<RecyclerView.Adapter> observerAdapter;
    private static WeakReference<Context> contextWeakReference;
    private static MyHandler myHandler;
    private static DownloadMissionManageUtil downloadMissionManageUtil;


    private static class MyHandler extends Handler {

        private WeakReference<DownloadMissionManageUtil> weakReference;

        private MyHandler(DownloadMissionManageUtil downloadMissionManageUtil) {
            this.weakReference = new WeakReference<>(downloadMissionManageUtil);
        }

        @Override
        public void handleMessage(Message msg) {
            DownloadMissionManageUtil downloadMissionManageUtil = weakReference.get();
            if (downloadMissionManageUtil != null) {
                downloadMissionManageUtil.handlerMessage(msg);
            }
        }
    }

    private void handlerMessage(Message msg) {
        DownloadMissionPojo downloadMissionPojo = (DownloadMissionPojo) msg.obj;
        downloadMissionStateUpdate(downloadMissionPojo);
    }

    private DownloadMissionManageUtil() {

    }

    public static ArrayList<DownloadMissionPojo> getMissionList() {
        return missionList;
    }


    /**
     * 创建NotificationChannel
     * <p>
     * 在Android 8.0以上版本中，桌面图标可以在有消息通知时出现一个小红点，用户可以长安图标，弹出消息提示
     */
    private static NotificationChannel createNotificationChannel(boolean importance) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                    NOTIFICATION_CHANNEL_NAME, importance ? NotificationManager.IMPORTANCE_HIGH :
                    NotificationManager.IMPORTANCE_LOW);
            //应用图标提示点颜色
            channel.setLightColor(Color.BLUE);
            //是否在久按桌面图标时显示此渠道的通知
            channel.setShowBadge(true);
            //是否允许震动
            channel.enableVibration(true);
            //是否允许控制手机通知灯
            channel.enableLights(true);
            notificationManager.createNotificationChannel(channel);
            return channel;
        } else {
            return null;
        }
    }

    /**
     * 文件断点续传下载工具初始化方法
     * 请在自定义application或mainActivity中的onCreate中调用此方法
     *
     * @param context
     */
    public static void initDownloadMissionManageUtil(Context context) {

        downloadMissionManageUtil = new DownloadMissionManageUtil();
        myHandler = new MyHandler(downloadMissionManageUtil);
        contextWeakReference = new WeakReference<>(context);
        notificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel notificationChannel = createNotificationChannel(false);
            if (notificationChannel != null) {
                notificationBuilder = new NotificationCompat.Builder(context,
                        notificationChannel.getId());
            } else {
                notificationBuilder = new NotificationCompat.Builder(context);
            }
        } else {
            notificationBuilder = new NotificationCompat.Builder(context);
        }

        if (!"".equals(ShareData.getShareStringData(DOWNLOADMISSIONS_CACHE_KEY))) {
            Type type = new TypeToken<ArrayList<DownloadMissionPojo>>() {
            }.getType();
            ArrayList<DownloadMissionPojo> missions =
                    Util.getGsonInstance().fromJson(ShareData.getShareStringData(DOWNLOADMISSIONS_CACHE_KEY), type);
            missionList.addAll(missions);
        }
    }

    /**
     * 关闭所有下载任务，并保存下载任务进度到本地SharedPreference
     * 请在mainActivity的onDestory()方法中调用此方法
     */
    public static void destroyDownloadMissionManageUtil() {
        if (notificationManager != null) {
            notificationManager.cancelAll();
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && notificationManager != null) {
            try {
                notificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        for (DownloadMissionPojo downloadMissionPojo : missionList) {
            downloadMissionPojo.setDownloadState(DownloadMissionPojo.DOWNLOADSTATE_PAUSE);
            downloadMissionPojo.setDownloadSpeed(0);
        }
        taskArray.clear();
        ShareData.setShareStringData(DOWNLOADMISSIONS_CACHE_KEY,
                Util.getGsonInstance().toJson(missionList));
        //慎用static引用数据类型,如果使用，不用时要进行处理
        missionList.clear();
        downloadMissionManageUtil = null;
    }

    /**
     * 设置activity界面的列表适配器  以便更新状态
     *
     * @param adapter
     */
    public static void setObserverAdapter(RecyclerView.Adapter adapter) {
        observerAdapter = new WeakReference<>(adapter);
    }

    /**
     * 新建下载任务
     *
     * @param downloadMissionPojo
     */
    public static void addMission(DownloadMissionPojo downloadMissionPojo) {

        downloadMissionPojo.setDownloadState(DownloadMissionPojo.DOWNLOADSTATE_DOWNLOADING);
        missionList.add(downloadMissionPojo);
        RecyclerView.Adapter adapter;
        if ((adapter = observerAdapter.get()) != null) {
            adapter.notifyItemInserted(missionList.size() - 1);
        }
        AsyncTaskForDownloadFile task = new AsyncTaskForDownloadFile(downloadMissionPojo,
                myHandler);
        taskArray.put(downloadMissionPojo.getMissionID(), task);
        task.executeOnExecutor(Util.getExecutorService());
        notifyNotification(downloadMissionPojo);
    }


    /**
     * 已存在的下载任务更新当前进度与状态
     *
     * @param downloadMissionPojo
     */
    public static void downloadMissionStateUpdate(DownloadMissionPojo downloadMissionPojo) {

        //判断是否下载完毕
        if (downloadMissionPojo.getFileSize() != 0
                && (downloadMissionPojo.getReadSize() >= downloadMissionPojo.getFileSize())) {

            downloadMissionPojo.setDownloadState(DownloadMissionPojo.DOWNLOADSTATE_COMPLETED);
        }

        switch (downloadMissionPojo.getDownloadState()) {
            case DownloadMissionPojo.DOWNLOADSTATE_COMPLETED:
                downloadMissionCompleted(downloadMissionPojo);
                break;
            case DownloadMissionPojo.DOWNLOADSTATE_DOWNLOADING:
                //如果当前已经存在一个对应下载任务且未执行完的线程，只更改下载任务状态即可
                // 如果没有,就重新创建一个下载线程继续下载任务
                AsyncTask task = taskArray.get(downloadMissionPojo.getMissionID());
                if (task == null || task.getStatus() != AsyncTask.Status.RUNNING) {
                    AsyncTaskForDownloadFile asyncTaskForDownloadFile =
                            new AsyncTaskForDownloadFile(downloadMissionPojo, myHandler);
                    //将下载线程保存或覆盖已经finished的线程
                    taskArray.put(downloadMissionPojo.getMissionID(), asyncTaskForDownloadFile);
                    asyncTaskForDownloadFile.executeOnExecutor(Util.getExecutorService());
                } else {
                    RecyclerView.Adapter adapter;
                    if ((adapter = observerAdapter.get()) != null) {
                        adapter.notifyItemChanged(missionList.indexOf(downloadMissionPojo));
                    }
                }
                notifyNotification(downloadMissionPojo);
                break;
            default:
                break;
        }
    }


    /**
     * 任务下载完成
     *
     * @param downloadMissionPojo
     */
    private static void downloadMissionCompleted(DownloadMissionPojo downloadMissionPojo) {
        if (contextWeakReference.get() != null) {
            //发广播 通知栏取消
            Intent downloadCompleted = new Intent(BROADCAST_MISSIONCOMPLETED);
            downloadCompleted.putExtra(FILE_ADDRESS_INTENT_KEY, downloadMissionPojo.getFilePath());
            LocalBroadcastManager.getInstance(contextWeakReference.get()).sendBroadcast(downloadCompleted);
        }
        notificationManager.cancel(downloadMissionPojo.getMissionID());
        missionList.remove(downloadMissionPojo);
        RecyclerView.Adapter adapter;
        if ((adapter = observerAdapter.get()) != null) {
            int changedItemPosition = missionList.indexOf(downloadMissionPojo);
            missionList.remove(downloadMissionPojo);
            adapter.notifyItemRemoved(changedItemPosition);
            adapter.notifyItemRangeChanged(changedItemPosition, missionList.size() - 1);
        }
        //如果adapter不为空那么该对象已经被移除，本行代码将不起作用
        missionList.remove(downloadMissionPojo);
        taskArray.remove(downloadMissionPojo.getMissionID());
    }


    /**
     * 任务被取消
     *
     * @param downloadMissionPojo
     */
    public static void downloadMissionancelled(DownloadMissionPojo downloadMissionPojo) {
        downloadMissionPojo.setDownloadState(DownloadMissionPojo.DOWNLOADSTATE_CNACLED);
        RecyclerView.Adapter adapter;
        if ((adapter = observerAdapter.get()) != null) {
            int changedItemPosition = missionList.indexOf(downloadMissionPojo);
            missionList.remove(downloadMissionPojo);
            adapter.notifyItemRemoved(changedItemPosition);
            adapter.notifyItemRangeChanged(changedItemPosition, missionList.size() - 1);
        }
        //如果adapter不为空那么该对象已经被移除，本行代码将不起作用
        missionList.remove(downloadMissionPojo);
        notificationManager.cancel(downloadMissionPojo.getMissionID());
        taskArray.remove(downloadMissionPojo.getMissionID());
        File file = new File(downloadMissionPojo.getFilePath());
        try {
            file.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载任务暂停
     *
     * @param missionId
     */
    public static void downloadMissionPause(int missionId) {
        notificationManager.cancel(missionId);
    }


    /**
     * 展示下载任务通知栏
     *
     * @return
     */
    private static void notifyNotification(DownloadMissionPojo downloadMissionPojo) {
        // notificationBuilder.setTicker("动漫之家");//状态栏消息滚动说明
        notificationBuilder.setContentTitle(downloadMissionPojo.getFileName());
        notificationBuilder.setContentText("文件下载中...");
        notificationBuilder.setWhen(System.currentTimeMillis());
        //android 6.0以上，SmallIcon需要使用白色图标，否则android会把不透明的部分全部绘制成白色
        notificationBuilder.setSmallIcon(R.drawable.notificationlogodownload);
//        Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);xcz x
//        notificationBuilder.setLargeIcon(bitmap);

        //设置带进度条的通知栏 前提是使用通知栏默认的布局
        //第三个参数为设置进度条样式,true : 不确定式进度条，false : 精确自增式进度条
        notificationBuilder.setProgress(Math.round(downloadMissionPojo.getFileSize())
                , Math.round(downloadMissionPojo.getReadSize()), false);

        //5.0以上横幅消息推送
        //情况1:设置消息优先级 从Android 5.0开始，如果notification  priority设置为HIGH, MAX,
        // 并且设置了notificationbuilder.setDefaults(NotificationCompat.DEFAULT_ALL)
        //情况2:设置setfullscreenintent();
        notificationBuilder.setPriority(NotificationCompat.PRIORITY_MAX);

        //设置点击后不取消
        //notificationBuilder.setAutoCancel(false);
        //Ongoing为true的通知不能手动清除 setAutoCancel和setOngoing调用一个即可
        notificationBuilder.setOngoing(true);

        /**
         设置通知可见性

         您的应用可以控制在安全锁定屏幕上显示的通知中可见的详细级别。 调用 setVisibility() 并指定以下值之一:

         VISIBILITY_PUBLIC 显示通知的完整内容。
         VISIBILITY_SECRET 不会在锁定屏幕上显示此通知的任何部分。
         VISIBILITY_PRIVATE 显示通知图标和内容标题等基本信息，但是隐藏通知的完整内容。
         **/
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //5.0系统以上，锁屏界面显示
            notificationBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
        }

        PendingIntent pendingIntent;
        if ((pendingIntent = notificationClick()) != null) {
            notificationBuilder.setContentIntent(pendingIntent);
        }
        Notification notification = notificationBuilder.build();
        notificationManager.notify(downloadMissionPojo.getMissionID(), notification);
    }

    /**
     * @return 通知栏执行点击事件
     */
    private static PendingIntent notificationClick() {
        if (contextWeakReference.get() != null) {
            Intent i = new Intent();
            i.setClass(contextWeakReference.get(), DownLoadScheduleActivity.class);
            return PendingIntent.getActivity(contextWeakReference.get(), 1001, i,
                    PendingIntent.FLAG_UPDATE_CURRENT);
        } else {
            return null;
        }
    }
}